/****************************************************************************
 * Copyright (C) 2009-2010 GGA Software Services LLC
 *
 * This file may be distributed and/or modified under the terms of the
 * GNU Affero General Public License version 3 as published by the Free
 * Software Foundation and appearing in the file LICENSE.GPL included in
 * the packaging of this file.
 *
 * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
 * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 ***************************************************************************/

if(!window.util)
	util = {};

util.Map = function (obj)
{
	if(typeof (obj) !== 'undefined' && obj.constructor !== Object)
		throw Error("Passed object is not an instance of 'Object'!");
	this._obj = obj ||
	{};
	this._count = 0;
};

util.Map.prototype.each = function (func, context)
{
	for(var v in this._obj)
	{
		var v_int = parseInt(v);
		var value = this._obj[v];

		if(!isNaN(v_int))
			v = v_int;
		func.call(context, v, value)
	}
};

util.Map.prototype.map = function (func, context)
{
	var ret = new util.Map();
	this.each(function (v, value)
	{
		ret.set(v, func.call(context, v, value));
	}, this);
	return ret;
};

util.Map.prototype.find = function (func, context)
{
	for(var v in this._obj)
	{
		var v_int = parseInt(v);
		var value = this._obj[v];

		if(!isNaN(v_int))
			v = v_int;
		if(func.call(context, v, value))
			return v;
	}
};

util.Map.prototype.findAll = function (func, context)
{
	var vv = [];
	for(var v in this._obj)
	{
		var v_int = parseInt(v);
		var value = this._obj[v];
		if(!isNaN(v_int))
			v = v_int;
		if(func.call(context, v, value))
			vv.push(v);
	}
	return vv;
};

util.Map.prototype.keys = function ()
{
	var keys = [];
	for(var v in this._obj)
	{
		keys.push(v);
	}
	return keys;
};

util.Map.prototype.ikeys = function ()
{
	var keys = [];
	for(var v in this._obj)
	{
		keys.push(v - 0);
	}
	return keys;
};

util.Map.prototype.set = function (key, value)
{
	this._count += (typeof (value) !== 'undefined' ? 1 : 0) - (typeof (this._obj[key]) !== 'undefined' ? 1 : 0);
	if(typeof (value) === 'undefined')
	{
		var val = this._obj[key];
		delete this._obj[key];
		return val;
	}
	else
	{
		return this._obj[key] = value;
	}
};

util.Map.prototype.get = function (key)
{
	if(this._obj[key] !== Object.prototype[key])
		return this._obj[key];
	return undefined;
};

util.Map.prototype.has = function (key)
{
	return(this._obj[key] !== Object.prototype[key]);
};

util.Map.prototype.unset = function (key)
{
	return this.set(key, undefined);
};

util.Map.prototype.update = function (object)
{
	for(var v in object)
		this.set(v, object[v]);
};

util.Map.prototype.clear = function ()
{
	this._obj = {};
	this._count = 0;
};

util.Map.prototype.count = function ()
{
	return this._count;
};

util.Map.prototype.idList = function ()
{
	return util.idList(this._obj);
};

util.Map.prototype.keyOf = function (value)
{
	for(var key in this._obj)
		if(this._obj[key] === value) return key;
};
